package me.bincker.formwork.web.core.entity

import com.fasterxml.jackson.annotation.JsonFilter
import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
import com.fasterxml.jackson.annotation.JsonView
import me.bincker.formwork.web.core.config.jackson.filter.JsonHideViewPropertyFilter
import me.bincker.formwork.web.core.config.jackson.view.NameView
import me.bincker.formwork.web.core.config.jackson.view.ReadView
import me.bincker.formwork.web.core.validated.ValidAdd
import me.bincker.formwork.web.core.validated.ValidPut
import org.hibernate.annotations.GenericGenerator
import org.hibernate.collection.spi.PersistentCollection
import org.springframework.data.annotation.CreatedDate
import org.springframework.data.annotation.LastModifiedDate
import org.springframework.data.jpa.domain.support.AuditingEntityListener
import java.io.Serializable
import java.util.*
import javax.persistence.EntityListeners
import javax.persistence.GeneratedValue
import javax.persistence.Id
import javax.persistence.MappedSuperclass
import javax.validation.constraints.NotEmpty
import kotlin.reflect.full.memberProperties

@EntityListeners(AuditingEntityListener::class)
@MappedSuperclass
@JsonFilter(JsonHideViewPropertyFilter.FILTER_NAME)
@JsonIgnoreProperties("hibernateLazyInitializer")
open class BaseEntity: Serializable {
    @Id
    @GenericGenerator(name = "uuidGenerator", strategy = "org.hibernate.id.UUIDGenerator")
    @GeneratedValue(generator = "uuidGenerator")
    @JsonView(ReadView::class, NameView::class)
    @NotEmpty(groups = [ValidAdd::class, ValidPut::class])
    var id: String? = null

    @CreatedDate
    @JsonView(ReadView::class)
    var createdDate: Date? = null

    @LastModifiedDate
    @JsonView(ReadView::class)
    var lastModifiedDate: Date? = null

    @JsonIgnore
    fun isNew() = this.id == null

    override fun toString(): String {
        return this::class.memberProperties.joinToString(",", this::class.simpleName + "(", ")") { property->
            val value = property.call(this)
            return@joinToString if(value is PersistentCollection){
                property.name + "=(LAZY)"
            }else {
                property.name + "=" + value
            }
        }
    }
}